#ifndef _SOCKETREACTOR_HPP_
#define _SOCKETREACTOR_HPP_

#include "jhdefs.hpp"
#include "net/Socket.hpp"
#include "net/SocketNotification.hpp"
#include "stdlib/timespan.hpp"
using JHCPP::stdlib::CTimeSpan;
#include "msg/abstractobserver.hpp"
using JHCPP::msg::CAbstractObserver;
#include "utils/autoptr.hpp"
using JHCPP::utils::TAutoPtr;
#include "thread/thread.hpp"
using JHCPP::thread::CThread;
#include <map>

NET_NAMESPACE_BEGIN

class CSocketNotifier;

class CSocketReactor : public CRunnable
{
public:
	CSocketReactor();
	explicit CSocketReactor(const CTimeSpan& timeout);
	virtual ~CSocketReactor();

	void run();
	void stop();
	void wakeUp();

	void setTimeout(const CTimeSpan& timeout);
	const CTimeSpan& getTimeout() const;

	void addEventHandler(const CSocket& socket, const CAbstractObserver& observer);
	bool hasEventHandler(const CSocket& socket, const CAbstractObserver& observer);
	void removeEventHandler(const CSocket& socket, const CAbstractObserver& observer);

protected:
	virtual void onTimeout();
	virtual void onIdle();
	virtual void onShutdown();
	virtual void onBusy();
	void dispatch(const CSocket& socket, CSocketNotification* pNotification);
	void dispatch(CSocketNotification* pNotification);

private:
	typedef TAutoPtr<CSocketNotifier>     NotifierPtr;
	typedef TAutoPtr<CSocketNotification> NotificationPtr;
	typedef std::map<CSocket, NotifierPtr>     EventHandlerMap;

	void dispatch(NotifierPtr& pNotifier, CSocketNotification* pNotification);

	enum
	{
		DEFAULT_TIMEOUT = 250000
	};

	bool            m_stop;
	CTimeSpan		m_timeout;
	EventHandlerMap m_handlers;
	NotificationPtr m_pReadableNotification;
	NotificationPtr m_pWritableNotification;
	NotificationPtr m_pErrorNotification;
	NotificationPtr m_pTimeoutNotification;
	NotificationPtr m_pIdleNotification;
	NotificationPtr m_pShutdownNotification;
	CMutex			m_mutex;
	CThread*		m_pThread;

	friend class CSocketNotifier;
};

NET_NAMESPACE_END

#endif